package com.project.server.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.project.server.common.exception.BusinessException;
import com.project.server.entity.HealthRecord;
import com.project.server.mapper.HealthRecordMapper;
import com.project.server.service.HealthRecordService;
import com.project.server.vo.HealthReportVO;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class HealthRecordServiceImpl implements HealthRecordService {

    @Autowired
    private HealthRecordMapper healthRecordMapper;

    @Override
    public Page<HealthRecord> getRecordList(Long userId, Integer current, Integer size, Integer type) {
        Page<HealthRecord> page = new Page<>(current, size);

        LambdaQueryWrapper<HealthRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(HealthRecord::getUserId, userId)
                .eq(type != null, HealthRecord::getRecordType, type)
                .orderByDesc(HealthRecord::getMeasureTime);

        return healthRecordMapper.selectPage(page, wrapper);
    }

    @Override
    public void addRecord(HealthRecord record) {
        record.setCreateTime(LocalDateTime.now());
        record.setUpdateTime(LocalDateTime.now());
        record.setMeasureTime(LocalDateTime.now());
        healthRecordMapper.insert(record);
    }

    @Override
    @Transactional
    public void deleteRecord(Long id) {
        healthRecordMapper.deleteById(id);
    }

    @Override
    public void exportRecords(Long userId, Integer type, String startDate, String endDate, HttpServletResponse response) {
        try {
            // 设置响应头
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("健康记录", StandardCharsets.UTF_8).replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

            // 查询数据
            LambdaQueryWrapper<HealthRecord> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(HealthRecord::getUserId, userId)
                    .eq(type != null, HealthRecord::getRecordType, type);

            // 添加时间范围条件
            if (StringUtils.hasText(startDate)) {
                wrapper.ge(HealthRecord::getMeasureTime, LocalDateTime.parse(startDate));
            }
            if (StringUtils.hasText(endDate)) {
                wrapper.le(HealthRecord::getMeasureTime, LocalDateTime.parse(endDate));
            }

            wrapper.orderByDesc(HealthRecord::getMeasureTime);
            List<HealthRecord> records = healthRecordMapper.selectList(wrapper);

            // 准备Excel数据
            List<Map<String, Object>> excelData = records.stream().map(record -> {
                Map<String, Object> data = new HashMap<>();
                data.put("类型", getRecordTypeName(record.getRecordType()));
                data.put("数值", record.getRecordValue().toString());
                data.put("测量时间", record.getMeasureTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                data.put("备注", record.getRemark());
                return data;
            }).collect(Collectors.toList());

            // 写入Excel
            EasyExcel.write(response.getOutputStream())
                    .sheet("健康记录")
                    .doWrite(excelData);

        } catch (Exception e) {
            throw new BusinessException("导出失败：" + e.getMessage());
        }
    }

    @Override
    public HealthReportVO generateHealthReport(Long userId, String startDate, String endDate) {
        HealthReportVO report = new HealthReportVO();

        // 解析日期
        LocalDateTime start = startDate != null ?
            LocalDateTime.parse(startDate + "T00:00:00") :
            LocalDateTime.now().minusDays(30);
        LocalDateTime end = endDate != null ?
            LocalDateTime.parse(endDate + "T23:59:59") :
            LocalDateTime.now();

        // 查询时间范围内的记录
        LambdaQueryWrapper<HealthRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(HealthRecord::getUserId, userId)
               .between(HealthRecord::getMeasureTime, start, end)
               .orderByAsc(HealthRecord::getMeasureTime);

        List<HealthRecord> records = healthRecordMapper.selectList(wrapper);

        // 初始化数据容器
        Map<String, List<BigDecimal>> valueMap = new HashMap<>();
        Map<String, List<HealthReportVO.Point>> trendMap = new HashMap<>();
        String[] types = {"bloodPressure", "bloodSugar", "weight", "temperature"};

        for (String type : types) {
            valueMap.put(type, new ArrayList<>());
            trendMap.put(type, new ArrayList<>());
        }

        // 处理记录数据
        for (HealthRecord record : records) {
            String type = getTypeKey(record.getRecordType());
            if (type == null) continue;

            // 处理血压特殊情况
            if (record.getRecordType() == 1) {
                String[] values = record.getRecordValue().split("/");
                if (values.length == 2) {
                    valueMap.get(type).add(new BigDecimal(values[0])); // 收缩压

                    // 添加趋势点
                    HealthReportVO.Point point = new HealthReportVO.Point();
                    point.setDate(record.getMeasureTime().format(DateTimeFormatter.ISO_DATE));
                    point.setValue(new BigDecimal(values[0]));
                    trendMap.get(type).add(point);
                }
            } else {
                BigDecimal value = new BigDecimal(record.getRecordValue());
                valueMap.get(type).add(value);

                // 添加趋势点
                HealthReportVO.Point point = new HealthReportVO.Point();
                point.setDate(record.getMeasureTime().format(DateTimeFormatter.ISO_DATE));
                point.setValue(value);
                trendMap.get(type).add(point);
            }
        }

        // 计算统计值
        report.setAverageValues(calculateAverages(valueMap));
        report.setMaxValues(calculateMaxValues(valueMap));
        report.setMinValues(calculateMinValues(valueMap));
        report.setTrends(trendMap);

        // 生成分析报告
        report.setAnalysis(generateAnalysis(report));

        return report;
    }

    private String getTypeKey(Integer recordType) {
        switch (recordType) {
            case 1: return "bloodPressure";
            case 2: return "bloodSugar";
            case 3: return "weight";
            case 4: return "temperature";
            default: return null;
        }
    }

    private Map<String, BigDecimal> calculateAverages(Map<String, List<BigDecimal>> valueMap) {
        Map<String, BigDecimal> averages = new HashMap<>();
        valueMap.forEach((type, values) -> {
            if (!values.isEmpty()) {
                BigDecimal sum = values.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
                averages.put(type, sum.divide(new BigDecimal(values.size()), 1, RoundingMode.HALF_UP));
            }
        });
        return averages;
    }

    private Map<String, BigDecimal> calculateMaxValues(Map<String, List<BigDecimal>> valueMap) {
        Map<String, BigDecimal> maxValues = new HashMap<>();
        valueMap.forEach((type, values) -> {
            if (!values.isEmpty()) {
                maxValues.put(type, values.stream().max(BigDecimal::compareTo).get());
            }
        });
        return maxValues;
    }

    private Map<String, BigDecimal> calculateMinValues(Map<String, List<BigDecimal>> valueMap) {
        Map<String, BigDecimal> minValues = new HashMap<>();
        valueMap.forEach((type, values) -> {
            if (!values.isEmpty()) {
                minValues.put(type, values.stream().min(BigDecimal::compareTo).get());
            }
        });
        return minValues;
    }

    private String generateAnalysis(HealthReportVO report) {
        StringBuilder analysis = new StringBuilder();
        Map<String, BigDecimal> avgValues = report.getAverageValues();

        // 血压分析
        if (avgValues.containsKey("bloodPressure")) {
            BigDecimal avgSystolic = avgValues.get("bloodPressure");
            analysis.append("血压情况：\n");
            if (avgSystolic.compareTo(new BigDecimal("140")) > 0) {
                analysis.append("您的平均收缩压偏高，建议：\n");
                analysis.append("1. 控制饮食，减少盐分摄入\n");
                analysis.append("2. 保持规律运动\n");
                analysis.append("3. 定期监测血压\n");
            } else if (avgSystolic.compareTo(new BigDecimal("90")) < 0) {
                analysis.append("您的平均收缩压偏低，建议：\n");
                analysis.append("1. 适当增加盐分摄入\n");
                analysis.append("2. 保持充足休息\n");
            } else {
                analysis.append("您的血压控制良好，请继续保持。\n");
            }
        }

        // 血糖分析
        if (avgValues.containsKey("bloodSugar")) {
            BigDecimal avgSugar = avgValues.get("bloodSugar");
            analysis.append("\n血糖情况：\n");
            if (avgSugar.compareTo(new BigDecimal("7.0")) > 0) {
                analysis.append("您的平均血糖偏高，建议：\n");
                analysis.append("1. 控制碳水化合物摄入\n");
                analysis.append("2. 规律运动\n");
                analysis.append("3. 遵医嘱用药\n");
            } else {
                analysis.append("您的血糖控制在正常范围内。\n");
            }
        }

        return analysis.toString();
    }

    @Override
    public List<HealthRecord> getLatestRecords(Long userId) {
        // 创建查询条件
        List<HealthRecord> result = new ArrayList<>();

        // 查询每种类型的最新记录
        for (int type = 1; type <= 4; type++) {
            LambdaQueryWrapper<HealthRecord> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(HealthRecord::getUserId, userId)
                  .eq(HealthRecord::getRecordType, type)
                  .orderByDesc(HealthRecord::getMeasureTime)
                  .last("LIMIT 1");  // 只取最新的一条

            HealthRecord record = healthRecordMapper.selectOne(wrapper);
            if (record != null) {
                result.add(record);
            }
        }

        return result;
    }

    /**
     * 获取记录类型名称
     */
    private String getRecordTypeName(Integer recordType) {
        switch (recordType) {
            case 1:
                return "血压";
            case 2:
                return "血糖";
            case 3:
                return "体重";
            case 4:
                return "体温";
            default:
                return "未知类型";
        }
    }
}
